package cn.jacksigxu.min3halla.datagen;

import cn.jacksigxu.min3halla.MHMod;
import cn.jacksigxu.min3halla.block.IngredientCanBlock;
import cn.jacksigxu.min3halla.block.drink.MutableAlcoholDrinkBlock;
import cn.jacksigxu.min3halla.init.MHBlocks;
import net.minecraft.data.PackOutput;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraftforge.client.model.generators.BlockModelBuilder;
import net.minecraftforge.client.model.generators.BlockStateProvider;
import net.minecraftforge.client.model.generators.ConfiguredModel;
import net.minecraftforge.client.model.generators.ModelFile;
import net.minecraftforge.common.data.ExistingFileHelper;

public class ModBlockStateProvider extends BlockStateProvider {

    public ModBlockStateProvider(PackOutput output, ExistingFileHelper exFileHelper) {
        super(output, MHMod.MOD_ID, exFileHelper);
    }

    @Override
    protected void registerStatesAndModels() {
        horizontalBlock(MHBlocks.DRINK_MIXER.get(), file("block/drink_mixer"));
        simpleBlockWithItem(MHBlocks.FERMENT_BARREL.get(), models().cubeBottomTop("ferment_barrel", MHMod.loc("block/ferment_barrel_side"),
                MHMod.loc("block/ferment_barrel_bottom"), MHMod.loc("block/ferment_barrel_top")));
        horizontalBlock(MHBlocks.BTC_FILLING_MACHINE.get(), file("block/btc_filling_machine"));

        smallIngredientCanBlock(MHBlocks.BTC_CAN_BLOCK.get(), "btc_can");
        smallIngredientCanBlock(MHBlocks.ADELHYDE_BLOCK.get(), "adelhyde");
        smallIngredientCanBlock(MHBlocks.BRONSON_EXTRACT_BLOCK.get(), "bronson_extract");
        smallIngredientCanBlock(MHBlocks.POWDERED_DELTA_BLOCK.get(), "powdered_delta");
        smallIngredientCanBlock(MHBlocks.FLANERGIDE_BLOCK.get(), "flanergide");
        smallIngredientCanBlock(MHBlocks.KARMOTRINE_BLOCK.get(), "karmotrine");

        ingredientCanBlock(MHBlocks.HYPER_ACID_X_BLOCK.get(), "hyper_acid_x");
        ingredientCanBlock(MHBlocks.GLITCH_LIQUID_BLOCK.get(), "glitch_liquid");

        horizontalBlock(MHBlocks.FRIED_RICE_BLOCK.get(), file("block/fried_rice"));

        sizedDrink(MHBlocks.BAD_TOUCH_BLOCK.get(), file("block/bad_touch"), file("block/bad_touch_big"));
        sizedDrink(MHBlocks.BEER_BLOCK.get(), file("block/beer"), file("block/beer_big"));
        sizedDrink(MHBlocks.BLEEDING_JANE_BLOCK.get(), file("block/bleeding_jane"), file("block/bleeding_jane_big"));
        sizedDrink(MHBlocks.BLOOM_LIGHT_BLOCK.get(), file("block/bloom_light"), file("block/bloom_light_big"));
        mutableAlcoholDrink(MHBlocks.BLUE_FAIRY_BLOCK.get(), file("block/blue_fairy"), file("block/blue_fairy_big"));
        sizedDrink(MHBlocks.BRANDTINI_BLOCK.get(), file("block/bloom_light"), file("block/bloom_light_big"));
        sizedDrink(MHBlocks.COBALT_VELVET_BLOCK.get(), file("block/cobalt_velvet"), file("block/cobalt_velvet_big"));
        mutableAlcoholDrink(MHBlocks.CREVICE_SPIKE_BLOCK.get(), file("block/crevice_spike"), file("block/crevice_spike_big"));
        horizontalBlock(MHBlocks.FLAMING_MOAI_BLOCK.get(), file("block/flaming_moai"));
        mutableAlcoholDrink(MHBlocks.FLUFFY_DREAM_BLOCK.get(), file("block/fluffy_dream"), file("block/fluffy_dream_big"));
        sizedDrink(MHBlocks.FRINGE_WEAVER_BLOCK.get(), file("block/fringe_weaver"), file("block/fringe_weaver_big"));
        sizedDrink(MHBlocks.FROTHY_WATER_BLOCK.get(), file("block/beer"), file("block/beer_big"));
        sizedDrink(MHBlocks.GRIZZLY_TEMPLE_BLOCK.get(), file("block/grizzly_temple"), file("block/grizzly_temple_big"));
        mutableAlcoholDrink(MHBlocks.GUT_PUNCH_BLOCK.get(), file("block/gut_punch"), file("block/gut_punch_big"));
        horizontalBlock(MHBlocks.MARSBLAST_BLOCK.get(), file("block/marsblast"));
        sizedDrink(MHBlocks.MERCURYBLAST_BLOCK.get(), file("block/mercuryblast"), file("block/mercuryblast_big"));
        sizedDrink(MHBlocks.MOONBLAST_BLOCK.get(), file("block/moonblast"), file("block/moonblast_big"));
        horizontalBlock(MHBlocks.PIANO_MAN_BLOCK.get(), file("block/piano_man"));
        horizontalBlock(MHBlocks.PIANO_WOMAN_BLOCK.get(), file("block/piano_woman"));
        sizedDrink(MHBlocks.PILE_DRIVER_BLOCK.get(), file("block/pile_driver"), file("block/pile_driver_big"));
        mutableAlcoholDrink(MHBlocks.SPARKLE_STAR_BLOCK.get(), file("block/sparkle_star"), file("block/sparkle_star_big"));
        mutableAlcoholDrink(MHBlocks.SUGAR_RUSH_BLOCK.get(), file("block/sugar_rush"), file("block/sugar_rush_big"));
        mutableAlcoholDrink(MHBlocks.SUNSHINE_CLOUD_BLOCK.get(), file("block/sunshine_cloud"), file("block/sunshine_cloud_big"));
        sizedDrink(MHBlocks.SUPLEX_BLOCK.get(), file("block/suplex"), file("block/suplex_big"));
        horizontalBlock(MHBlocks.ZEN_STAR_BLOCK.get(), file("block/zen_star"));

        horizontalBlock(MHBlocks.MULAN_TEA_BLOCK.get(), file("block/mulan_tea"));
        horizontalBlock(MHBlocks.A_FEDORA_BLOCK.get(), file("block/a_fedora"));
        horizontalBlock(MHBlocks.RUM_BLOCK.get(), file("block/rum"));
        horizontalBlock(MHBlocks.ABSINTHE_BLOCK.get(), file("block/absinthe"));

        sizedDrink(MHBlocks.SEPTWOLVES_BLOCK.get(), file("block/septwolves"), file("block/septwolves_big"));
        horizontalBlock(MHBlocks.ALARM_LAMP_BLOCK.get(), file("block/alarm_lamp"));
        horizontalBlock(MHBlocks.SUPERB_BASKETBALL_BLOCK.get(), file("block/superb_basketball"));
        horizontalBlock(MHBlocks.FOX_WINE_BLOCK.get(), file("block/fox_wine"));

        horizontalBlock(MHBlocks.ERROR_DRINK_BLOCK.get(), file("block/error_drink"));
    }

    public void ingredientCanBlock(Block block, ModelFile model1, ModelFile model2, ModelFile model3, ModelFile model4) {
        horizontalBlock(block, state -> switch (state.getValue(IngredientCanBlock.COUNT)) {
            case 1 -> model1;
            case 2 -> model2;
            case 3 -> model3;
            default -> model4;
        });
    }

    public void ingredientCanBlock(Block block, String path) {
        horizontalBlock(block, state -> switch (state.getValue(IngredientCanBlock.COUNT)) {
            case 1 -> ingredientBuilder(path, 1);
            case 2 -> ingredientBuilder(path, 2);
            case 3 -> ingredientBuilder(path, 3);
            default -> ingredientBuilder(path, 4);
        });
    }

    public void smallIngredientCanBlock(Block block, String path) {
        horizontalBlock(block, state -> switch (state.getValue(IngredientCanBlock.COUNT)) {
            case 1 -> smallIngredientBuilder(path, 1);
            case 2 -> smallIngredientBuilder(path, 2);
            case 3 -> smallIngredientBuilder(path, 3);
            default -> smallIngredientBuilder(path, 4);
        });
    }

    private BlockModelBuilder ingredientBuilder(String name, int count) {
        return models().withExistingParent("block/" + name + "_" + count, MHMod.loc("block/base/ingredient_block_" + count))
                .texture("0", MHMod.loc("block/" + name))
                .texture("particle", MHMod.loc("item/" + name));
    }

    private BlockModelBuilder smallIngredientBuilder(String name, int count) {
        return models().withExistingParent("block/" + name + "_" + count, MHMod.loc("block/base/small_ingredient_block_" + count))
                .texture("0", MHMod.loc("block/" + name))
                .texture("particle", MHMod.loc("item/" + name));
    }

    public void sizedDrink(Block block, ModelFile defaultModel, ModelFile bigModel) {
        horizontalBlock(block, state -> state.getValue(MutableAlcoholDrinkBlock.DOUBLE_INGREDIENTS) ? bigModel : defaultModel);
    }

    public void mutableAlcoholDrink(Block block, ModelFile model) {
        getVariantBuilder(block)
                .forAllStatesExcept(state -> ConfiguredModel.builder()
                                .modelFile(model)
                                .rotationY(((int) state.getValue(BlockStateProperties.HORIZONTAL_FACING).toYRot() + 180) % 360)
                                .build(),
                        MutableAlcoholDrinkBlock.ALCOHOL);
    }

    public void mutableAlcoholDrink(Block block, ModelFile defaultModel, ModelFile bigModel) {
        getVariantBuilder(block)
                .forAllStatesExcept(state -> {
                            if (state.getValue(MutableAlcoholDrinkBlock.DOUBLE_INGREDIENTS)) {
                                return ConfiguredModel.builder()
                                        .modelFile(bigModel)
                                        .rotationY(((int) state.getValue(BlockStateProperties.HORIZONTAL_FACING).toYRot() + 180) % 360)
                                        .build();
                            } else {
                                return ConfiguredModel.builder()
                                        .modelFile(defaultModel)
                                        .rotationY(((int) state.getValue(BlockStateProperties.HORIZONTAL_FACING).toYRot() + 180) % 360)
                                        .build();
                            }
                        },
                        MutableAlcoholDrinkBlock.ALCOHOL);
    }

    public ModelFile file(String path) {
        return new ModelFile.UncheckedModelFile(modLoc(path));
    }
}
